package com.jplus.mvc.util;

import com.jplus.core.utill.JUtil;

/**
 * CRC-16/DNP x16+x13+x12+x11+x10+x8+x6+x5+x2+1 <br>
 * 是低位在前，高位在后。
 * 
 * @see http://www.ip33.com/crc.html
 * @author Yuanqy
 * @Date 2019年7月8日
 * @company http://www.lianyuplus.com/
 */
public class CRC16 {

	public static void main(String[] args) {
		byte[] data = JUtil.hex2Bytes("112223");
		byte[] crc = buildCRC16(data, data.length);
		System.out.println("校验位:" + JUtil.byte2Hex((crc)));
		short crc2 = build(data, data.length);
		System.out.println("校验位:" + JUtil.byte2Hex(LittleEndian.get(crc2)));
	}

	/******************************************************************************
	 * 生成crc16 <br/>
	 * Name: CRC-16/DNP x16+x13+x12+x11+x10+x8+x6+x5+x2+1 <br>
	 * Poly: 0x3D65 <br>
	 * Init:0x0000 <br>
	 * Refin: True <br>
	 * Refout: True <br>
	 * Xorout: 0xFFFF <br>
	 * Use: M-Bus,ect.<br>
	 *****************************************************************************/
	public static short build(byte[] buf, int len) {
		int crc = 0x0000;// Initial value
		int temp, i = 0;
		for (int x = 0; x < len; x++) {
			temp = buf[x] < 0 ? buf[x] & 0xFF : buf[x];// byte [-128~127]
			crc ^= temp; // crc ^= *data; data++;
			for (i = 0; i < 8; ++i) {
				if ((crc & 1) > 0)
					crc = (crc >> 1) ^ 0xA6BC; // 0xA6BC = reverse 0x3D65
				else
					crc = (crc >> 1);
			}
		}
		return (short) (crc ^ 0xFFFF); // crc^Xorout
	}

	/** 已废弃 */
	@Deprecated
	static byte[] buildCRC16(byte[] buf, int len) {
		// ==【改动部分：将byte转为16进制字符后处理】==========
		String hex = JUtil.byte2Hex(buf);
		// System.out.println("Ascii :" + hex);
		buf = hex.getBytes();
		len *= 2;
		// =================================================
		Integer crc = 0x0000;// Initial value
		int temp, i = 0;
		for (int x = 0; x < len; x++) {
			temp = buf[x] < 0 ? buf[x] & 0xFF : buf[x];// byte [-128~127]
			crc ^= temp; // crc ^= *data; data++;
			for (i = 0; i < 8; ++i) {
				if ((crc & 1) > 0)
					crc = (crc >> 1) ^ 0xA6BC; // 0xA6BC = reverse 0x3D65
				else
					crc = (crc >> 1);
			}
		}
		return LittleEndian.get((short) (crc ^ 0xFFFF)); // crc^Xorout
	}
}
